home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 1.iso / dist / fw_emacs-lisp-intro.idb / usr / freeware / info / emacs-lisp-intro.info-14.z / emacs-lisp-intro.info-14
Text File  |  2002-07-08  |  46KB  |  1,255 lines

  1. This is emacs-lisp-intro.info, produced by makeinfo version 4.0b from
  2. emacs-lisp-intro.texi.
  3.  
  4. INFO-DIR-SECTION Emacs
  5. START-INFO-DIR-ENTRY
  6. * Emacs Lisp Intro: (eintr).
  7.               A simple introduction to Emacs Lisp programming.
  8. END-INFO-DIR-ENTRY
  9.  
  10.    This is an introduction to `Programming in Emacs Lisp', for people
  11. who are not programmers.
  12.  
  13.    Edition 2.04, 2001 Dec 17
  14.  
  15.    Copyright (C) 1990, '91, '92, '93, '94, '95, '97, 2001 Free Software
  16. Foundation, Inc.
  17.  
  18.    Permission is granted to copy, distribute and/or modify this document
  19. under the terms of the GNU Free Documentation License, Version 1.1 or
  20. any later version published by the Free Software Foundation; with the
  21. Invariant Section being the Preface, with the Front-Cover Texts being
  22. no Front-Cover Texts, and with the Back-Cover Texts being no Back-Cover
  23. Texts.  A copy of the license is included in the section entitled "GNU
  24. Free Documentation License".
  25.  
  26. 
  27. File: emacs-lisp-intro.info,  Node: rotate-yk-ptr negative arg,  Prev: rotate-yk-ptr arg,  Up: yank
  28.  
  29. Passing a negative argument
  30. ...........................
  31.  
  32.    Finally, the question arises, what happens if either the remainder
  33. function, `%', or the `nthcdr' function is passed a negative argument,
  34. as they quite well may?
  35.  
  36.    The answers can be found by a quick test.  When `(% -1 5)' is
  37. evaluated, a negative number is returned; and if `nthcdr' is called
  38. with a negative number, it returns the same value as if it were called
  39. with a first argument of zero.  This can be seen be evaluating the
  40. following code.
  41.  
  42.    Here the `=>' points to the result of evaluating the code preceding
  43. it.  This was done by positioning the cursor after the code and typing
  44. `C-x C-e' (`eval-last-sexp') in the usual fashion.  You can do this if
  45. you are reading this in Info inside of GNU Emacs.
  46.  
  47.      (% -1 5)
  48.           => -1
  49.      
  50.      (setq animals '(cats dogs elephants))
  51.           => (cats dogs elephants)
  52.      
  53.      (nthcdr 1 animals)
  54.           => (dogs elephants)
  55.      
  56.      (nthcdr 0 animals)
  57.           => (cats dogs elephants)
  58.      
  59.      (nthcdr -1 animals)
  60.           => (cats dogs elephants)
  61.  
  62.    So, if a minus sign or a negative number is passed to `yank', the
  63. `kill-ring-yank-point' is rotated backwards until it reaches the
  64. beginning of the list.  Then it stays there.  Unlike the other case,
  65. when it jumps from the end of the list to the beginning of the list,
  66. making a ring, it stops.  This makes sense.  You often want to get back
  67. to the most recently clipped out piece of text, but you don't usually
  68. want to insert text from as many as thirty kill commands ago.  So you
  69. need to work through the ring to get to the end, but won't cycle around
  70. it inadvertently if you are trying to come back to the beginning.
  71.  
  72.    Incidentally, any number passed to `yank' with a minus sign
  73. preceding it will be treated as -1.  This is evidently a simplification
  74. for writing the program.  You don't need to jump back towards the
  75. beginning of the kill ring more than one place at a time and doing this
  76. is easier than writing a function to determine the magnitude of the
  77. number that follows the minus sign.
  78.  
  79. 
  80. File: emacs-lisp-intro.info,  Node: yank-pop,  Prev: yank,  Up: Kill Ring
  81.  
  82. `yank-pop'
  83. ==========
  84.  
  85.    After understanding `yank', the `yank-pop' function is easy.
  86. Leaving out the documentation to save space, it looks like this:
  87.  
  88.      (defun yank-pop (arg)
  89.        (interactive "*p")
  90.        (if (not (eq last-command 'yank))
  91.            (error "Previous command was not a yank"))
  92.        (setq this-command 'yank)
  93.        (let ((before (< (point) (mark))))
  94.          (delete-region (point) (mark))
  95.          (rotate-yank-pointer arg)
  96.          (set-mark (point))
  97.          (insert (car kill-ring-yank-pointer))
  98.          (if before (exchange-point-and-mark))))
  99.  
  100.    The function is interactive with a small `p' so the prefix argument
  101. is processed and passed to the function.  The command can only be used
  102. after a previous yank; otherwise an error message is sent.  This check
  103. uses the variable `last-command' which is discussed elsewhere.  (*Note
  104. copy-region-as-kill::.)
  105.  
  106.    The `let' clause sets the variable `before' to true or false
  107. depending whether point is before or after mark and then the region
  108. between point and mark is deleted.  This is the region that was just
  109. inserted by the previous yank and it is this text that will be
  110. replaced.  Next the `kill-ring-yank-pointer' is rotated so that the
  111. previously inserted text is not reinserted yet again.  Mark is set at
  112. the beginning of the place the new text will be inserted and then the
  113. first element to which `kill-ring-yank-pointer' points is inserted.
  114. This leaves point after the new text.  If in the previous yank, point
  115. was left before the inserted text, point and mark are now exchanged so
  116. point is again left in front of the newly inserted text.  That is all
  117. there is to it!
  118.  
  119. 
  120. File: emacs-lisp-intro.info,  Node: Full Graph,  Next: GNU Free Documentation License,  Prev: Kill Ring,  Up: Top
  121.  
  122. A Graph with Labelled Axes
  123. **************************
  124.  
  125.    Printed axes help you understand a graph.  They convey scale.  In an
  126. earlier chapter (*note Readying a Graph: Readying a Graph.), we wrote
  127. the code to print the body of a graph.  Here we write the code for
  128. printing and labelling vertical and horizontal axes, along with the
  129. body itself.
  130.  
  131. * Menu:
  132.  
  133. * Labelled Example::
  134. * print-graph Varlist::         `let' expression in `print-graph'.
  135. * print-Y-axis::                Print a label for the vertical axis.
  136. * print-X-axis::                Print a horizontal label.
  137. * Print Whole Graph::           The function to print a complete graph.
  138.  
  139. 
  140. File: emacs-lisp-intro.info,  Node: Labelled Example,  Next: print-graph Varlist,  Prev: Full Graph,  Up: Full Graph
  141.  
  142. Labelled Example Graph
  143. ======================
  144.  
  145.    Since insertions fill a buffer to the right and below point, the new
  146. graph printing function should first print the Y or vertical axis, then
  147. the body of the graph, and finally the X or horizontal axis.  This
  148. sequence lays out for us the contents of the function:
  149.  
  150.   1. Set up code.
  151.  
  152.   2. Print Y axis.
  153.  
  154.   3. Print body of graph.
  155.  
  156.   4. Print X axis.
  157.  
  158.    Here is an example of how a finished graph should look:
  159.  
  160.          10 -
  161.                        *
  162.                        *  *
  163.                        *  **
  164.                        *  ***
  165.           5 -      *   *******
  166.                  * *** *******
  167.                  *************
  168.                ***************
  169.           1 - ****************
  170.               |   |    |    |
  171.               1   5   10   15
  172.  
  173. In this graph, both the vertical and the horizontal axes are labelled
  174. with numbers.  However, in some graphs, the horizontal axis is time and
  175. would be better labelled with months, like this:
  176.  
  177.           5 -      *
  178.                  * ** *
  179.                  *******
  180.                ********** **
  181.           1 - **************
  182.               |    ^      |
  183.               Jan  June   Jan
  184.  
  185.    Indeed, with a little thought, we can easily come up with a variety
  186. of vertical and horizontal labelling schemes.  Our task could become
  187. complicated.  But complications breed confusion.  Rather than permit
  188. this, it is better choose a simple labelling scheme for our first
  189. effort, and to modify or replace it later.
  190.  
  191.    These considerations suggest the following outline for the
  192. `print-graph' function:
  193.  
  194.      (defun print-graph (numbers-list)
  195.        "DOCUMENTATION..."
  196.        (let ((height  ...
  197.              ...))
  198.          (print-Y-axis height ... )
  199.          (graph-body-print numbers-list)
  200.          (print-X-axis ... )))
  201.  
  202.    We can work on each part of the `print-graph' function definition in
  203. turn.
  204.  
  205. 
  206. File: emacs-lisp-intro.info,  Node: print-graph Varlist,  Next: print-Y-axis,  Prev: Labelled Example,  Up: Full Graph
  207.  
  208. The `print-graph' Varlist
  209. =========================
  210.  
  211.    In writing the `print-graph' function, the first task is to write
  212. the varlist in the `let' expression.  (We will leave aside for the
  213. moment any thoughts about making the function interactive or about the
  214. contents of its documentation string.)
  215.  
  216.    The varlist should set several values.  Clearly, the top of the label
  217. for the vertical axis must be at least the height of the graph, which
  218. means that we must obtain this information here.  Note that the
  219. `print-graph-body' function also requires this information.  There is
  220. no reason to calculate the height of the graph in two different places,
  221. so we should change `print-graph-body' from the way we defined it
  222. earlier to take advantage of the calculation.
  223.  
  224.    Similarly, both the function for printing the X axis labels and the
  225. `print-graph-body' function need to learn the value of the width of
  226. each symbol.  We can perform the calculation here and change the
  227. definition for `print-graph-body' from the way we defined it in the
  228. previous chapter.
  229.  
  230.    The length of the label for the horizontal axis must be at least as
  231. long as the graph.  However, this information is used only in the
  232. function that prints the horizontal axis, so it does not need to be
  233. calculated here.
  234.  
  235.    These thoughts lead us directly to the following form for the varlist
  236. in the `let' for `print-graph':
  237.  
  238.      (let ((height (apply 'max numbers-list)) ; First version.
  239.            (symbol-width (length graph-blank)))
  240.  
  241. As we shall see, this expression is not quite right.
  242.  
  243. 
  244. File: emacs-lisp-intro.info,  Node: print-Y-axis,  Next: print-X-axis,  Prev: print-graph Varlist,  Up: Full Graph
  245.  
  246. The `print-Y-axis' Function
  247. ===========================
  248.  
  249.    The job of the `print-Y-axis' function is to print a label for the
  250. vertical axis that looks like this:
  251.  
  252.          10 -
  253.      
  254.      
  255.      
  256.      
  257.           5 -
  258.      
  259.      
  260.      
  261.           1 -
  262.  
  263. The function should be passed the height of the graph, and then should
  264. construct and insert the appropriate numbers and marks.
  265.  
  266.    It is easy enough to see in the figure what the Y axis label should
  267. look like; but to say in words, and then to write a function definition
  268. to do the job is another matter.  It is not quite true to say that we
  269. want a number and a tic every five lines: there are only three lines
  270. between the `1' and the `5' (lines 2, 3, and 4), but four lines between
  271. the `5' and the `10' (lines 6, 7, 8, and 9).  It is better to say that
  272. we want a number and a tic mark on the base line (number 1) and then
  273. that we want a number and a tic on the fifth line from the bottom and
  274. on every line that is a multiple of five.
  275.  
  276. * Menu:
  277.  
  278. * Height of label::             What height for the Y axis?
  279. * Compute a Remainder::         How to compute the remainder of a division.
  280. * Y Axis Element::              Construct a line for the Y axis.
  281. * Y-axis-column::               Generate a list of Y axis labels.
  282. * print-Y-axis Penultimate::    A not quite final version.
  283.  
  284. 
  285. File: emacs-lisp-intro.info,  Node: Height of label,  Next: Compute a Remainder,  Prev: print-Y-axis,  Up: print-Y-axis
  286.  
  287. What height should the label be?
  288. --------------------------------
  289.  
  290.    The next issue is what height the label should be?  Suppose the
  291. maximum height of tallest column of the graph is seven.  Should the
  292. highest label on the Y axis be `5 -', and should the graph stick up
  293. above the label?  Or should the highest label be `7 -', and mark the
  294. peak of the graph?  Or should the highest label be `10 -', which is a
  295. multiple of five, and be higher than the topmost value of the graph?
  296.  
  297.    The latter form is preferred.  Most graphs are drawn within
  298. rectangles whose sides are an integral number of steps long--5, 10, 15,
  299. and so on for a step distance of five.  But as soon as we decide to use
  300. a step height for the vertical axis, we discover that the simple
  301. expression in the varlist for computing the height is wrong.  The
  302. expression is `(apply 'max numbers-list)'.  This returns the precise
  303. height, not the maximum height plus whatever is necessary to round up
  304. to the nearest multiple of five.  A more complex expression is required.
  305.  
  306.    As usual in cases like this, a complex problem becomes simpler if it
  307. is divided into several smaller problems.
  308.  
  309.    First, consider the case when the highest value of the graph is an
  310. integral multiple of five--when it is 5, 10, 15 ,or some higher
  311. multiple of five.  We can use this value as the Y axis height.
  312.  
  313.    A fairly simply way to determine whether a number is a multiple of
  314. five is to divide it by five and see if the division results in a
  315. remainder.  If there is no remainder, the number is a multiple of five.
  316. Thus, seven divided by five has a remainder of two, and seven is not
  317. an integral multiple of five.  Put in slightly different language, more
  318. reminiscent of the classroom, five goes into seven once, with a
  319. remainder of two.  However, five goes into ten twice, with no
  320. remainder: ten is an integral multiple of five.
  321.  
  322. 
  323. File: emacs-lisp-intro.info,  Node: Compute a Remainder,  Next: Y Axis Element,  Prev: Height of label,  Up: print-Y-axis
  324.  
  325. Side Trip: Compute a Remainder
  326. ------------------------------
  327.  
  328.    In Lisp, the function for computing a remainder is `%'.  The
  329. function returns the remainder of its first argument divided by its
  330. second argument.  As it happens, `%' is a function in Emacs Lisp that
  331. you cannot discover using `apropos': you find nothing if you type `M-x
  332. apropos <RET> remainder <RET>'.  The only way to learn of the existence
  333. of `%' is to read about it in a book such as this or in the Emacs Lisp
  334. sources.  The `%' function is used in the code for
  335. `rotate-yank-pointer', which is described in an appendix.  (*Note The
  336. Body of `rotate-yank-pointer': rotate-yk-ptr body.)
  337.  
  338.    You can try the `%' function by evaluating the following two
  339. expressions:
  340.  
  341.      (% 7 5)
  342.      
  343.      (% 10 5)
  344.  
  345. The first expression returns 2 and the second expression returns 0.
  346.  
  347.    To test whether the returned value is zero or some other number, we
  348. can use the `zerop' function.  This function returns `t' if its
  349. argument, which must be a number, is zero.
  350.  
  351.      (zerop (% 7 5))
  352.           => nil
  353.      
  354.      (zerop (% 10 5))
  355.           => t
  356.  
  357.    Thus, the following expression will return `t' if the height of the
  358. graph is evenly divisible by five:
  359.  
  360.      (zerop (% height 5))
  361.  
  362. (The value of `height', of course, can be found from `(apply 'max
  363. numbers-list)'.)
  364.  
  365.    On the other hand, if the value of `height' is not a multiple of
  366. five, we want to reset the value to the next higher multiple of five.
  367. This is straightforward arithmetic using functions with which we are
  368. already familiar.  First, we divide the value of `height' by five to
  369. determine how many times five goes into the number.  Thus, five goes
  370. into twelve twice.  If we add one to this quotient and multiply by
  371. five, we will obtain the value of the next multiple of five that is
  372. larger than the height.  Five goes into twelve twice.  Add one to two,
  373. and multiply by five; the result is fifteen, which is the next multiple
  374. of five that is higher than twelve.  The Lisp expression for this is:
  375.  
  376.      (* (1+ (/ height 5)) 5)
  377.  
  378. For example, if you evaluate the following, the result is 15:
  379.  
  380.      (* (1+ (/ 12 5)) 5)
  381.  
  382.    All through this discussion, we have been using `five' as the value
  383. for spacing labels on the Y axis; but we may want to use some other
  384. value.  For generality, we should replace `five' with a variable to
  385. which we can assign a value.  The best name I can think of for this
  386. variable is `Y-axis-label-spacing'.
  387.  
  388.    Using this term, and an `if' expression, we produce the following:
  389.  
  390.      (if (zerop (% height Y-axis-label-spacing))
  391.          height
  392.        ;; else
  393.        (* (1+ (/ height Y-axis-label-spacing))
  394.           Y-axis-label-spacing))
  395.  
  396. This expression returns the value of `height' itself if the height is
  397. an even multiple of the value of the `Y-axis-label-spacing' or else it
  398. computes and returns a value of `height' that is equal to the next
  399. higher multiple of the value of the `Y-axis-label-spacing'.
  400.  
  401.    We can now include this expression in the `let' expression of the
  402. `print-graph' function (after first setting the value of
  403. `Y-axis-label-spacing'):
  404.  
  405.      (defvar Y-axis-label-spacing 5
  406.        "Number of lines from one Y axis label to next.")
  407.      
  408.      ...
  409.      (let* ((height (apply 'max numbers-list))
  410.             (height-of-top-line
  411.              (if (zerop (% height Y-axis-label-spacing))
  412.                  height
  413.                ;; else
  414.                (* (1+ (/ height Y-axis-label-spacing))
  415.                   Y-axis-label-spacing)))
  416.             (symbol-width (length graph-blank))))
  417.      ...
  418.  
  419. (Note use of the  `let*' function: the initial value of height is
  420. computed once by the `(apply 'max numbers-list)' expression and then
  421. the resulting value of  `height' is used to compute its final value.
  422. *Note The `let*' expression: fwd-para let, for more about `let*'.)
  423.  
  424. 
  425. File: emacs-lisp-intro.info,  Node: Y Axis Element,  Next: Y-axis-column,  Prev: Compute a Remainder,  Up: print-Y-axis
  426.  
  427. Construct a Y Axis Element
  428. --------------------------
  429.  
  430.    When we print the vertical axis, we want to insert strings such as
  431. `5 -' and `10 - ' every five lines.  Moreover, we want the numbers and
  432. dashes to line up, so shorter numbers must be padded with leading
  433. spaces.  If some of the strings use two digit numbers, the strings with
  434. single digit numbers must include a leading blank space before the
  435. number.
  436.  
  437.    To figure out the length of the number, the `length' function is
  438. used.  But the `length' function works only with a string, not with a
  439. number.  So the number has to be converted from being a number to being
  440. a string.  This is done with the `number-to-string' function.  For
  441. example,
  442.  
  443.      (length (number-to-string 35))
  444.           => 2
  445.      
  446.      (length (number-to-string 100))
  447.           => 3
  448.  
  449. (`number-to-string' is also called `int-to-string'; you will see this
  450. alternative name in various sources.)
  451.  
  452.    In addition, in each label, each number is followed by a string such
  453. as ` - ', which we will call the `Y-axis-tic' marker.  This variable is
  454. defined with `defvar':
  455.  
  456.      (defvar Y-axis-tic " - "
  457.         "String that follows number in a Y axis label.")
  458.  
  459.    The length of the Y label is the sum of the length of the Y axis tic
  460. mark and the length of the number of the top of the graph.
  461.  
  462.      (length (concat (number-to-string height) Y-axis-tic)))
  463.  
  464.    This value will be calculated by the `print-graph' function in its
  465. varlist as `full-Y-label-width' and passed on.  (Note that we did not
  466. think to include this in the varlist when we first proposed it.)
  467.  
  468.    To make a complete vertical axis label, a tic mark is concatenated
  469. with a number; and the two together may be preceded by one or more
  470. spaces depending on how long the number is.  The label consists of
  471. three parts: the (optional) leading spaces, the number, and the tic
  472. mark.  The function is passed the value of the number for the specific
  473. row, and the value of the width of the top line, which is calculated
  474. (just once) by `print-graph'.
  475.  
  476.      (defun Y-axis-element (number full-Y-label-width)
  477.        "Construct a NUMBERed label element.
  478.      A numbered element looks like this `  5 - ',
  479.      and is padded as needed so all line up with
  480.      the element for the largest number."
  481.        (let* ((leading-spaces
  482.               (- full-Y-label-width
  483.                  (length
  484.                   (concat (number-to-string number)
  485.                           Y-axis-tic)))))
  486.          (concat
  487.           (make-string leading-spaces ? )
  488.           (number-to-string number)
  489.           Y-axis-tic)))
  490.  
  491.    The `Y-axis-element' function concatenates together the leading
  492. spaces, if any; the number, as a string; and the tic mark.
  493.  
  494.    To figure out how many leading spaces the label will need, the
  495. function subtracts the actual length of the label--the length of the
  496. number plus the length of the tic mark--from the desired label width.
  497.  
  498.    Blank spaces are inserted using the `make-string' function.  This
  499. function takes two arguments: the first tells it how long the string
  500. will be and the second is a symbol for the character to insert, in a
  501. special format.  The format is a question mark followed by a blank
  502. space, like this, `? '.  *Note Character Type: (elisp)Character Type,
  503. for a description of the syntax for characters.
  504.  
  505.    The `number-to-string' function is used in the concatenation
  506. expression, to convert the number to a string that is concatenated with
  507. the leading spaces and the tic mark.
  508.  
  509. 
  510. File: emacs-lisp-intro.info,  Node: Y-axis-column,  Next: print-Y-axis Penultimate,  Prev: Y Axis Element,  Up: print-Y-axis
  511.  
  512. Create a Y Axis Column
  513. ----------------------
  514.  
  515.    The preceding functions provide all the tools needed to construct a
  516. function that generates a list of numbered and blank strings to insert
  517. as the label for the vertical axis:
  518.  
  519.      (defun Y-axis-column (height width-of-label)
  520.        "Construct list of Y axis labels and blank strings.
  521.      For HEIGHT of line above base and WIDTH-OF-LABEL."
  522.        (let (Y-axis)
  523.          (while (> height 1)
  524.            (if (zerop (% height Y-axis-label-spacing))
  525.                ;; Insert label.
  526.                (setq Y-axis
  527.                      (cons
  528.                       (Y-axis-element height width-of-label)
  529.                       Y-axis))
  530.              ;; Else, insert blanks.
  531.              (setq Y-axis
  532.                    (cons
  533.                     (make-string width-of-label ? )
  534.                     Y-axis)))
  535.            (setq height (1- height)))
  536.          ;; Insert base line.
  537.          (setq Y-axis
  538.                (cons (Y-axis-element 1 width-of-label) Y-axis))
  539.          (nreverse Y-axis)))
  540.  
  541.    In this function, we start with the value of `height' and
  542. repetitively subtract one from its value.  After each subtraction, we
  543. test to see whether the value is an integral multiple of the
  544. `Y-axis-label-spacing'.  If it is, we construct a numbered label using
  545. the `Y-axis-element' function; if not, we construct a blank label using
  546. the `make-string' function.  The base line consists of the number one
  547. followed by a tic mark.
  548.  
  549. 
  550. File: emacs-lisp-intro.info,  Node: print-Y-axis Penultimate,  Prev: Y-axis-column,  Up: print-Y-axis
  551.  
  552. The Not Quite Final Version of `print-Y-axis'
  553. ---------------------------------------------
  554.  
  555.    The list constructed by the `Y-axis-column' function is passed to
  556. the `print-Y-axis' function, which inserts the list as a column.
  557.  
  558.      (defun print-Y-axis (height full-Y-label-width)
  559.        "Insert Y axis using HEIGHT and FULL-Y-LABEL-WIDTH.
  560.      Height must be the maximum height of the graph.
  561.      Full width is the width of the highest label element."
  562.      ;; Value of height and full-Y-label-width
  563.      ;; are passed by `print-graph'.
  564.        (let ((start (point)))
  565.          (insert-rectangle
  566.           (Y-axis-column height full-Y-label-width))
  567.          ;; Place point ready for inserting graph.
  568.          (goto-char start)
  569.          ;; Move point forward by value of full-Y-label-width
  570.          (forward-char full-Y-label-width)))
  571.  
  572.    The `print-Y-axis' uses the `insert-rectangle' function to insert
  573. the Y axis labels created by the `Y-axis-column' function.  In
  574. addition, it places point at the correct position for printing the body
  575. of the graph.
  576.  
  577.    You can test `print-Y-axis':
  578.  
  579.   1. Install
  580.  
  581.           Y-axis-label-spacing
  582.           Y-axis-tic
  583.           Y-axis-element
  584.           Y-axis-column
  585.           print-Y-axis
  586.  
  587.   2. Copy the following expression:
  588.  
  589.           (print-Y-axis 12 5)
  590.  
  591.   3. Switch to the `*scratch*' buffer and place the cursor where you
  592.      want the axis labels to start.
  593.  
  594.   4. Type `M-:' (`eval-expression').
  595.  
  596.   5. Yank the `graph-body-print' expression into the minibuffer with
  597.      `C-y' (`yank)'.
  598.  
  599.   6. Press <RET> to evaluate the expression.
  600.  
  601.    Emacs will print labels vertically, the top one being `10 - '.  (The
  602. `print-graph' function will pass the value of `height-of-top-line',
  603. which in this case would end up as 15.)
  604.  
  605. 
  606. File: emacs-lisp-intro.info,  Node: print-X-axis,  Next: Print Whole Graph,  Prev: print-Y-axis,  Up: Full Graph
  607.  
  608. The `print-X-axis' Function
  609. ===========================
  610.  
  611.    X axis labels are much like Y axis labels, except that the tics are
  612. on a line above the numbers.  Labels should look like this:
  613.  
  614.          |   |    |    |
  615.          1   5   10   15
  616.  
  617.    The first tic is under the first column of the graph and is preceded
  618. by several blank spaces.  These spaces provide room in rows above for
  619. the Y axis labels.  The second, third, fourth, and subsequent tics are
  620. all spaced equally, according to the value of `X-axis-label-spacing'.
  621.  
  622.    The second row of the X axis consists of numbers, preceded by several
  623. blank spaces and also separated according to the value of the variable
  624. `X-axis-label-spacing'.
  625.  
  626.    The value of the variable `X-axis-label-spacing' should itself be
  627. measured in units of `symbol-width', since you may want to change the
  628. width of the symbols that you are using to print the body of the graph
  629. without changing the ways the graph is labelled.
  630.  
  631. * Menu:
  632.  
  633. * Similarities differences::    Much like `print-Y-axis', but not exactly.
  634. * X Axis Tic Marks::            Create tic marks for the horizontal axis.
  635.  
  636. 
  637. File: emacs-lisp-intro.info,  Node: Similarities differences,  Next: X Axis Tic Marks,  Prev: print-X-axis,  Up: print-X-axis
  638.  
  639. Similarities and differences
  640. ----------------------------
  641.  
  642.    The `print-X-axis' function is constructed in more or less the same
  643. fashion as the `print-Y-axis' function except that it has two lines:
  644. the line of tic marks and the numbers.  We will write a separate
  645. function to print each line and then combine them within the
  646. `print-X-axis' function.
  647.  
  648.    This is a three step process:
  649.  
  650.   1. Write a function to print the X axis tic marks,
  651.      `print-X-axis-tic-line'.
  652.  
  653.   2. Write a function to print the X numbers,
  654.      `print-X-axis-numbered-line'.
  655.  
  656.   3. Write a function to print both lines, the `print-X-axis' function,
  657.      using `print-X-axis-tic-line' and `print-X-axis-numbered-line'.
  658.  
  659. 
  660. File: emacs-lisp-intro.info,  Node: X Axis Tic Marks,  Prev: Similarities differences,  Up: print-X-axis
  661.  
  662. X Axis Tic Marks
  663. ----------------
  664.  
  665.    The first function should print the X axis tic marks.  We must
  666. specify the tic marks themselves and their spacing:
  667.  
  668.      (defvar X-axis-label-spacing
  669.        (if (boundp 'graph-blank)
  670.            (* 5 (length graph-blank)) 5)
  671.        "Number of units from one X axis label to next.")
  672.  
  673. (Note that the value of `graph-blank' is set by another `defvar'.  The
  674. `boundp' predicate checks whether it has already been set; `boundp'
  675. returns `nil' if it has not.  If `graph-blank' were unbound and we did
  676. not use this conditional construction, in GNU Emacs 21, we would enter
  677. the debugger and see an error message saying
  678. `Debugger entered--Lisp error: (void-variable graph-blank)'.)
  679.  
  680.    Here is the `defvar' for `X-axis-tic-symbol':
  681.  
  682.      (defvar X-axis-tic-symbol "|"
  683.        "String to insert to point to a column in X axis.")
  684.  
  685.    The goal is to make a line that looks like this:
  686.  
  687.             |   |    |    |
  688.  
  689.    The first tic is indented so that it is under the first column,
  690. which is indented to provide space for the Y axis labels.
  691.  
  692.    A tic element consists of the blank spaces that stretch from one tic
  693. to the next plus a tic symbol.  The number of blanks is determined by
  694. the width of the tic symbol and the `X-axis-label-spacing'.
  695.  
  696.    The code looks like this:
  697.  
  698.      ;;; X-axis-tic-element
  699.      ...
  700.      (concat
  701.       (make-string
  702.        ;; Make a string of blanks.
  703.        (-  (* symbol-width X-axis-label-spacing)
  704.            (length X-axis-tic-symbol))
  705.        ? )
  706.       ;; Concatenate blanks with tic symbol.
  707.       X-axis-tic-symbol)
  708.      ...
  709.  
  710.    Next, we determine how many blanks are needed to indent the first tic
  711. mark to the first column of the graph.  This uses the value of
  712. `full-Y-label-width' passed it by the `print-graph' function.
  713.  
  714.    The code to make `X-axis-leading-spaces' looks like this:
  715.  
  716.      ;; X-axis-leading-spaces
  717.      ...
  718.      (make-string full-Y-label-width ? )
  719.      ...
  720.  
  721.    We also need to determine the length of the horizontal axis, which is
  722. the length of the numbers list, and the number of tics in the horizontal
  723. axis:
  724.  
  725.      ;; X-length
  726.      ...
  727.      (length numbers-list)
  728.      
  729.      ;; tic-width
  730.      ...
  731.      (* symbol-width X-axis-label-spacing)
  732.      
  733.      ;; number-of-X-tics
  734.      (if (zerop (% (X-length tic-width)))
  735.          (/ (X-length tic-width))
  736.        (1+ (/ (X-length tic-width))))
  737.  
  738.    All this leads us directly to the function for printing the X axis
  739. tic line:
  740.  
  741.      (defun print-X-axis-tic-line
  742.        (number-of-X-tics X-axis-leading-spaces X-axis-tic-element)
  743.        "Print tics for X axis."
  744.          (insert X-axis-leading-spaces)
  745.          (insert X-axis-tic-symbol)  ; Under first column.
  746.          ;; Insert second tic in the right spot.
  747.          (insert (concat
  748.                   (make-string
  749.                    (-  (* symbol-width X-axis-label-spacing)
  750.                        ;; Insert white space up to second tic symbol.
  751.                        (* 2 (length X-axis-tic-symbol)))
  752.                    ? )
  753.                   X-axis-tic-symbol))
  754.          ;; Insert remaining tics.
  755.          (while (> number-of-X-tics 1)
  756.            (insert X-axis-tic-element)
  757.            (setq number-of-X-tics (1- number-of-X-tics))))
  758.  
  759.    The line of numbers is equally straightforward:
  760.  
  761.    First, we create a numbered element with blank spaces before each
  762. number:
  763.  
  764.      (defun X-axis-element (number)
  765.        "Construct a numbered X axis element."
  766.        (let ((leading-spaces
  767.               (-  (* symbol-width X-axis-label-spacing)
  768.                   (length (number-to-string number)))))
  769.          (concat (make-string leading-spaces ? )
  770.                  (number-to-string number))))
  771.  
  772.    Next, we create the function to print the numbered line, starting
  773. with the number "1" under the first column:
  774.  
  775.      (defun print-X-axis-numbered-line
  776.        (number-of-X-tics X-axis-leading-spaces)
  777.        "Print line of X-axis numbers"
  778.        (let ((number X-axis-label-spacing))
  779.          (insert X-axis-leading-spaces)
  780.          (insert "1")
  781.          (insert (concat
  782.                   (make-string
  783.                    ;; Insert white space up to next number.
  784.                    (-  (* symbol-width X-axis-label-spacing) 2)
  785.                    ? )
  786.                   (number-to-string number)))
  787.          ;; Insert remaining numbers.
  788.          (setq number (+ number X-axis-label-spacing))
  789.          (while (> number-of-X-tics 1)
  790.            (insert (X-axis-element number))
  791.            (setq number (+ number X-axis-label-spacing))
  792.            (setq number-of-X-tics (1- number-of-X-tics)))))
  793.  
  794.    Finally, we need to write the `print-X-axis' that uses
  795. `print-X-axis-tic-line' and `print-X-axis-numbered-line'.
  796.  
  797.    The function must determine the local values of the variables used
  798. by both `print-X-axis-tic-line' and `print-X-axis-numbered-line', and
  799. then it must call them.  Also, it must print the carriage return that
  800. separates the two lines.
  801.  
  802.    The function consists of a varlist that specifies five local
  803. variables, and calls to each of the two line printing functions:
  804.  
  805.      (defun print-X-axis (numbers-list)
  806.        "Print X axis labels to length of NUMBERS-LIST."
  807.        (let* ((leading-spaces
  808.                (make-string full-Y-label-width ? ))
  809.             ;; symbol-width is provided by graph-body-print
  810.             (tic-width (* symbol-width X-axis-label-spacing))
  811.             (X-length (length numbers-list))
  812.             (X-tic
  813.              (concat
  814.               (make-string
  815.                ;; Make a string of blanks.
  816.                (-  (* symbol-width X-axis-label-spacing)
  817.                    (length X-axis-tic-symbol))
  818.                ? )
  819.               ;; Concatenate blanks with tic symbol.
  820.               X-axis-tic-symbol))
  821.             (tic-number
  822.              (if (zerop (% X-length tic-width))
  823.                  (/ X-length tic-width)
  824.                (1+ (/ X-length tic-width)))))
  825.          (print-X-axis-tic-line tic-number leading-spaces X-tic)
  826.          (insert "\n")
  827.          (print-X-axis-numbered-line tic-number leading-spaces)))
  828.  
  829.    You can test `print-X-axis':
  830.  
  831.   1. Install `X-axis-tic-symbol', `X-axis-label-spacing',
  832.      `print-X-axis-tic-line', as well as `X-axis-element',
  833.      `print-X-axis-numbered-line', and `print-X-axis'.
  834.  
  835.   2. Copy the following expression:
  836.  
  837.           (progn
  838.            (let ((full-Y-label-width 5)
  839.                  (symbol-width 1))
  840.              (print-X-axis
  841.               '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16))))
  842.  
  843.   3. Switch to the `*scratch*' buffer and place the cursor where you
  844.      want the axis labels to start.
  845.  
  846.   4. Type `M-:' (`eval-expression').
  847.  
  848.   5. Yank the test expression into the minibuffer with `C-y' (`yank)'.
  849.  
  850.   6. Press <RET> to evaluate the expression.
  851.  
  852.    Emacs will print the horizontal axis like this:
  853.  
  854.           |   |    |    |    |
  855.           1   5   10   15   20
  856.  
  857. 
  858. File: emacs-lisp-intro.info,  Node: Print Whole Graph,  Prev: print-X-axis,  Up: Full Graph
  859.  
  860. Printing the Whole Graph
  861. ========================
  862.  
  863.    Now we are nearly ready to print the whole graph.
  864.  
  865.    The function to print the graph with the proper labels follows the
  866. outline we created earlier (*note A Graph with Labelled Axes: Full
  867. Graph.), but with additions.
  868.  
  869.    Here is the outline:
  870.  
  871.      (defun print-graph (numbers-list)
  872.        "DOCUMENTATION..."
  873.        (let ((height  ...
  874.              ...))
  875.          (print-Y-axis height ... )
  876.          (graph-body-print numbers-list)
  877.          (print-X-axis ... )))
  878.  
  879. * Menu:
  880.  
  881. * The final version::           A few changes.
  882. * Test print-graph::            Run a short test.
  883. * Graphing words in defuns::    Executing the final code.
  884. * lambda::                      How to write an anonymous function.
  885. * mapcar::                      Apply a function to elements of a list.
  886. * Another Bug::                 Yet another bug ... most insidious.
  887. * Final printed graph::         The graph itself!
  888.  
  889. 
  890. File: emacs-lisp-intro.info,  Node: The final version,  Next: Test print-graph,  Prev: Print Whole Graph,  Up: Print Whole Graph
  891.  
  892. Changes for the Final Version
  893. -----------------------------
  894.  
  895.    The final version is different from what we planned in two ways:
  896. first, it contains additional values calculated once in the varlist;
  897. second, it carries an option to specify the labels' increment per row.
  898. This latter feature turns out to be essential; otherwise, a graph may
  899. have more rows than fit on a display or on a sheet of paper.
  900.  
  901.    This new feature requires a change to the `Y-axis-column' function,
  902. to add `vertical-step' to it.  The function looks like this:
  903.  
  904.      ;;; Final version.
  905.      (defun Y-axis-column
  906.        (height width-of-label &optional vertical-step)
  907.        "Construct list of labels for Y axis.
  908.      HEIGHT is maximum height of graph.
  909.      WIDTH-OF-LABEL is maximum width of label.
  910.      VERTICAL-STEP, an option, is a positive integer
  911.      that specifies how much a Y axis label increments
  912.      for each line.  For example, a step of 5 means
  913.      that each line is five units of the graph."
  914.        (let (Y-axis
  915.              (number-per-line (or vertical-step 1)))
  916.          (while (> height 1)
  917.            (if (zerop (% height Y-axis-label-spacing))
  918.                ;; Insert label.
  919.                (setq Y-axis
  920.                      (cons
  921.                       (Y-axis-element
  922.                        (* height number-per-line)
  923.                        width-of-label)
  924.                       Y-axis))
  925.              ;; Else, insert blanks.
  926.              (setq Y-axis
  927.                    (cons
  928.                     (make-string width-of-label ? )
  929.                     Y-axis)))
  930.            (setq height (1- height)))
  931.          ;; Insert base line.
  932.          (setq Y-axis (cons (Y-axis-element
  933.                              (or vertical-step 1)
  934.                              width-of-label)
  935.                             Y-axis))
  936.          (nreverse Y-axis)))
  937.  
  938.    The values for the maximum height of graph and the width of a symbol
  939. are computed by `print-graph' in its `let' expression; so
  940. `graph-body-print' must be changed to accept them.
  941.  
  942.      ;;; Final version.
  943.      (defun graph-body-print (numbers-list height symbol-width)
  944.        "Print a bar graph of the NUMBERS-LIST.
  945.      The numbers-list consists of the Y-axis values.
  946.      HEIGHT is maximum height of graph.
  947.      SYMBOL-WIDTH is number of each column."
  948.        (let (from-position)
  949.          (while numbers-list
  950.            (setq from-position (point))
  951.            (insert-rectangle
  952.             (column-of-graph height (car numbers-list)))
  953.            (goto-char from-position)
  954.            (forward-char symbol-width)
  955.            ;; Draw graph column by column.
  956.            (sit-for 0)
  957.            (setq numbers-list (cdr numbers-list)))
  958.          ;; Place point for X axis labels.
  959.          (forward-line height)
  960.          (insert "\n")))
  961.  
  962.    Finally, the code for the `print-graph' function:
  963.  
  964.      ;;; Final version.
  965.      (defun print-graph
  966.        (numbers-list &optional vertical-step)
  967.        "Print labelled bar graph of the NUMBERS-LIST.
  968.      The numbers-list consists of the Y-axis values.
  969.      
  970.      Optionally, VERTICAL-STEP, a positive integer,
  971.      specifies how much a Y axis label increments for
  972.      each line.  For example, a step of 5 means that
  973.      each row is five units."
  974.        (let* ((symbol-width (length graph-blank))
  975.               ;; `height' is both the largest number
  976.               ;; and the number with the most digits.
  977.               (height (apply 'max numbers-list))
  978.               (height-of-top-line
  979.                (if (zerop (% height Y-axis-label-spacing))
  980.                    height
  981.                  ;; else
  982.                  (* (1+ (/ height Y-axis-label-spacing))
  983.                     Y-axis-label-spacing)))
  984.               (vertical-step (or vertical-step 1))
  985.               (full-Y-label-width
  986.                (length
  987.                 (concat
  988.                  (number-to-string
  989.                   (* height-of-top-line vertical-step))
  990.                  Y-axis-tic))))
  991.      
  992.          (print-Y-axis
  993.           height-of-top-line full-Y-label-width vertical-step)
  994.          (graph-body-print
  995.           numbers-list height-of-top-line symbol-width)
  996.          (print-X-axis numbers-list)))
  997.  
  998. 
  999. File: emacs-lisp-intro.info,  Node: Test print-graph,  Next: Graphing words in defuns,  Prev: The final version,  Up: Print Whole Graph
  1000.  
  1001. Testing `print-graph'
  1002. ---------------------
  1003.  
  1004.    We can test the `print-graph' function with a short list of numbers:
  1005.  
  1006.   1. Install the final versions of `Y-axis-column', `graph-body-print',
  1007.      and `print-graph' (in addition to the rest of the code.)
  1008.  
  1009.   2. Copy the following expression:
  1010.  
  1011.           (print-graph '(3 2 5 6 7 5 3 4 6 4 3 2 1))
  1012.  
  1013.   3. Switch to the `*scratch*' buffer and place the cursor where you
  1014.      want the axis labels to start.
  1015.  
  1016.   4. Type `M-:' (`eval-expression').
  1017.  
  1018.   5. Yank the test expression into the minibuffer with `C-y' (`yank)'.
  1019.  
  1020.   6. Press <RET> to evaluate the expression.
  1021.  
  1022.    Emacs will print a graph that looks like this:
  1023.  
  1024.      10 -
  1025.      
  1026.      
  1027.               *
  1028.              **   *
  1029.       5 -   ****  *
  1030.             **** ***
  1031.           * *********
  1032.           ************
  1033.       1 - *************
  1034.      
  1035.           |   |    |    |
  1036.           1   5   10   15
  1037.  
  1038.    On the other hand, if you pass `print-graph' a `vertical-step' value
  1039. of 2, by evaluating this expression:
  1040.  
  1041.      (print-graph '(3 2 5 6 7 5 3 4 6 4 3 2 1) 2)
  1042.  
  1043. The graph looks like this:
  1044.  
  1045.      20 -
  1046.      
  1047.      
  1048.               *
  1049.              **   *
  1050.      10 -   ****  *
  1051.             **** ***
  1052.           * *********
  1053.           ************
  1054.       2 - *************
  1055.      
  1056.           |   |    |    |
  1057.           1   5   10   15
  1058.  
  1059. (A question: is the `2' on the bottom of the vertical axis a bug or a
  1060. feature?  If you think it is a bug, and should be a `1' instead, (or
  1061. even a `0'), you can modify the sources.)
  1062.  
  1063. 
  1064. File: emacs-lisp-intro.info,  Node: Graphing words in defuns,  Next: lambda,  Prev: Test print-graph,  Up: Print Whole Graph
  1065.  
  1066. Graphing Numbers of Words and Symbols
  1067. -------------------------------------
  1068.  
  1069.    Now for the graph for which all this code was written: a graph that
  1070. shows how many function definitions contain fewer than 10 words and
  1071. symbols, how many contain between 10 and 19 words and symbols, how many
  1072. contain between 20 and 29 words and symbols, and so on.
  1073.  
  1074.    This is a multi-step process.  First make sure you have loaded all
  1075. the requisite code.
  1076.  
  1077.    It is a good idea to reset the value of `top-of-ranges' in case you
  1078. have set it to some different value.  You can evaluate the following:
  1079.  
  1080.      (setq top-of-ranges
  1081.       '(10  20  30  40  50
  1082.         60  70  80  90 100
  1083.        110 120 130 140 150
  1084.        160 170 180 190 200
  1085.        210 220 230 240 250
  1086.        260 270 280 290 300)
  1087.  
  1088. Next create a list of the number of words and symbols in each range.
  1089.  
  1090. Evaluate the following:
  1091.  
  1092.      (setq list-for-graph
  1093.             (defuns-per-range
  1094.               (sort
  1095.                (recursive-lengths-list-many-files
  1096.                 (directory-files "/usr/local/emacs/lisp"
  1097.                                  t ".+el$"))
  1098.                '<)
  1099.               top-of-ranges))
  1100.  
  1101. On my machine, this takes about an hour.  It looks though 303 Lisp
  1102. files in my copy of Emacs version 19.23.  After all that computing, the
  1103. `list-for-graph' has this value:
  1104.  
  1105.      (537 1027 955 785 594 483 349 292 224 199 166 120 116 99
  1106.      90 80 67 48 52 45 41 33 28 26 25 20 12 28 11 13 220)
  1107.  
  1108. This means that my copy of Emacs has 537 function definitions with
  1109. fewer than 10 words or symbols in them, 1,027 function definitions with
  1110. 10 to 19 words or symbols in them, 955 function definitions with 20 to
  1111. 29 words or symbols in them, and so on.
  1112.  
  1113.    Clearly, just by looking at this list we can see that most function
  1114. definitions contain ten to thirty words and symbols.
  1115.  
  1116.    Now for printing.  We do _not_ want to print a graph that is 1,030
  1117. lines high ...  Instead, we should print a graph that is fewer than
  1118. twenty-five lines high.  A graph that height can be displayed on almost
  1119. any monitor, and easily printed on a sheet of paper.
  1120.  
  1121.    This means that each value in `list-for-graph' must be reduced to
  1122. one-fiftieth its present value.
  1123.  
  1124.    Here is a short function to do just that, using two functions we have
  1125. not yet seen, `mapcar' and `lambda'.
  1126.  
  1127.      (defun one-fiftieth (full-range)
  1128.        "Return list, each number one-fiftieth of previous."
  1129.       (mapcar '(lambda (arg) (/ arg 50)) full-range))
  1130.  
  1131. 
  1132. File: emacs-lisp-intro.info,  Node: lambda,  Next: mapcar,  Prev: Graphing words in defuns,  Up: Print Whole Graph
  1133.  
  1134. A `lambda' Expression: Useful Anonymity
  1135. ---------------------------------------
  1136.  
  1137.    `lambda' is the symbol for an anonymous function, a function without
  1138. a name.  Every time you use an anonymous function, you need to include
  1139. its whole body.
  1140.  
  1141. Thus,
  1142.  
  1143.      (lambda (arg) (/ arg 50))
  1144.  
  1145. is a function definition that says `return the value resulting from
  1146. dividing whatever is passed to me as `arg' by 50'.
  1147.  
  1148.    Earlier, for example, we had a function `multiply-by-seven'; it
  1149. multiplied its argument by 7.  This function is similar, except it
  1150. divides its argument by 50; and, it has no name.  The anonymous
  1151. equivalent of `multiply-by-seven' is:
  1152.  
  1153.      (lambda (number) (* 7 number))
  1154.  
  1155. (*Note The `defun' Special Form: defun.)
  1156.  
  1157. If we want to multiply 3 by 7, we can write:
  1158.  
  1159.      (multiply-by-seven 3)
  1160.       \_______________/ ^
  1161.               |         |
  1162.            function  argument
  1163.  
  1164.  
  1165.  
  1166.  
  1167. This expression returns 21.
  1168.  
  1169. Similarly, we can write:
  1170.  
  1171.      ((lambda (number) (* 7 number)) 3)
  1172.       \____________________________/ ^
  1173.                     |                |
  1174.            anonymous function     argument
  1175.  
  1176.  
  1177.  
  1178.  
  1179. If we want to divide 100 by 50, we can write:
  1180.  
  1181.      ((lambda (arg) (/ arg 50)) 100)
  1182.       \______________________/  \_/
  1183.                   |              |
  1184.          anonymous function   argument
  1185.  
  1186.  
  1187.  
  1188.  
  1189. This expression returns 2.  The 100 is passed to the function, which
  1190. divides that number by 50.
  1191.  
  1192.    *Note Lambda Expressions: (elisp)Lambda Expressions, for more about
  1193. `lambda'.  Lisp and lambda expressions derive from the Lambda Calculus.
  1194.  
  1195. 
  1196. File: emacs-lisp-intro.info,  Node: mapcar,  Next: Another Bug,  Prev: lambda,  Up: Print Whole Graph
  1197.  
  1198. The `mapcar' Function
  1199. ---------------------
  1200.  
  1201.    `mapcar' is a function that calls its first argument with each
  1202. element of its second argument, in turn.  The second argument must be a
  1203. sequence.
  1204.  
  1205.    The `map' part of the name comes from the mathematical phrase,
  1206. `mapping over a domain', meaning to apply a function to each of the
  1207. elements in a domain.  The mathematical phrase is based on the metaphor
  1208. of a surveyor walking, one step at a time, over an area he is mapping.
  1209. And `car', of course, comes from the Lisp notion of the first of a list.
  1210.  
  1211. For example,
  1212.  
  1213.      (mapcar '1+ '(2 4 6))
  1214.           => (3 5 7)
  1215.  
  1216. The function `1+' which adds one to its argument, is executed on _each_
  1217. element of the list, and a new list is returned.
  1218.  
  1219.    Contrast this with `apply', which applies its first argument to all
  1220. the remaining.  (*Note Readying a Graph: Readying a Graph, for a
  1221. explanation of `apply'.)
  1222.  
  1223.    In the definition of `one-fiftieth', the first argument is the
  1224. anonymous function:
  1225.  
  1226.      (lambda (arg) (/ arg 50))
  1227.  
  1228. and the second argument is `full-range', which will be bound to
  1229. `list-for-graph'.
  1230.  
  1231.    The whole expression looks like this:
  1232.  
  1233.      (mapcar '(lambda (arg) (/ arg 50)) full-range))
  1234.  
  1235.    *Note Mapping Functions: (elisp)Mapping Functions, for more about
  1236. `mapcar'.
  1237.  
  1238.    Using the `one-fiftieth' function, we can generate a list in which
  1239. each element is one-fiftieth the size of the corresponding element in
  1240. `list-for-graph'.
  1241.  
  1242.      (setq fiftieth-list-for-graph
  1243.            (one-fiftieth list-for-graph))
  1244.  
  1245.    The resulting list looks like this:
  1246.  
  1247.      (10 20 19 15 11 9 6 5 4 3 3 2 2
  1248.      1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 4)
  1249.  
  1250. This, we are almost ready to print!  (We also notice the loss of
  1251. information: many of the higher ranges are 0, meaning that fewer than
  1252. 50 defuns had that many words or symbols--but not necessarily meaning
  1253. that none had that many words or symbols.)
  1254.  
  1255.